﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Markup;
using SilverTile.Sprites;

namespace SilverTile.Xaml
{
    [ContentProperty("Animations")]
    public class SpriteAnimation : FrameworkElement
    {

        public SpriteAnimation()
        {
            Animations = new List<FrameAnimation>();
        }

        public static readonly DependencyProperty XProperty = DependencyProperty.RegisterAttached("X", typeof(Int32), typeof(SpriteAnimation), null);

        public Int32 X
        {
            get { return (Int32)GetValue(XProperty); }
            set { SetValue(XProperty, value); }
        }

        public static readonly DependencyProperty YProperty = DependencyProperty.RegisterAttached("Y", typeof(Int32), typeof(SpriteAnimation), null);

        public Int32 Y
        {
            get { return (Int32)GetValue(YProperty); }
            set { SetValue(YProperty, value); }
        }

        public static readonly DependencyProperty FpsProperty = DependencyProperty.RegisterAttached("Fps", typeof(Int32), typeof(SpriteAnimation), new PropertyMetadata(10));

        public Int32 Fps
        {
            get { return (Int32)GetValue(FpsProperty); }
            set { SetValue(FpsProperty, value); }
        }

        public static readonly DependencyProperty AnimationsProperty = DependencyProperty.RegisterAttached("Animations", typeof(List<FrameAnimation>), typeof(SpriteAnimation),
            null);

        public List<FrameAnimation> Animations
        {
            get { return (List<FrameAnimation>)GetValue(AnimationsProperty); }
            set { SetValue(AnimationsProperty, value); }
        }

        public T GetAnimatedSprite<T>() where T : AnimatedSprite
        {
            return (T)GetAnimatedSprite(typeof(T));
        }

        public AnimatedSprite GetAnimatedSprite(Type spriteType)
        {

            if (!typeof(AnimatedSprite).IsAssignableFrom(spriteType))
            {
                throw new ArgumentOutOfRangeException("spriteType", "The sprite type must derive from AnimatedSprite");
            }

            System.Reflection.ConstructorInfo c = spriteType.GetConstructor(new Type[] { typeof(Int32), typeof(Int32) });
            if (c == null)
            {
                throw new ArgumentException("Type " + spriteType.Name + " has no suitable constructor!");
            }

            IFrame firstFrame = Animations.First().Frames.First().Frame;

            AnimatedSprite sprite = (AnimatedSprite)c.Invoke(new object[] { firstFrame.Width, firstFrame.Height });
            sprite.Fps = Fps;

            foreach (FrameAnimation animation in Animations)
            {
                sprite.AddAnimations(animation.Name, animation.Frames.Select(f => f.Frame).ToArray());
            }

            return sprite;
        }

    }
}
